package com.himiotech.core.framework.config.interceptor;

import cn.hutool.json.JSONUtil;
import com.himiotech.core.framework.config.HimioConfig;
import com.himiotech.core.framework.helper.exception.DemoException;
import com.himiotech.core.framework.helper.utils.ServletUtils;
import com.himiotech.core.framework.helper.utils.ShiroUtils;
import com.himiotech.core.project.model.entity.user.User;
import com.himiotech.core.project.web.base.model.HimioResult;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 演示模式过滤器
 *
 * @author wuwen
 */
@Component
public class DemoInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!HimioConfig.isDemoModeStatic()) {
            return true;
        }
        if (!ServletUtils.isAjaxRequest(request)) {
            return true;
        }

        Subject subject = ShiroUtils.getSubject();
        if (subject == null) {
            ServletUtils.renderString(response, JSONUtil.toJsonStr(HimioResult.errMsg("当前未登录或登录过期，请重新登录！")));
            return false;
        }

        User currentSessionUser = ShiroUtils.getSysUser();
        if (currentSessionUser.isAdmin()) {
            return true;
        }
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            if (!method.isAnnotationPresent(RequiresPermissions.class) &&
                    !method.isAnnotationPresent(RequiresRoles.class) &&
                    !method.isAnnotationPresent(RequiresAuthentication.class)) {
                return true;
            }
            RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
            boolean isListOrViewAuth = Arrays.stream(requiresPermissions.value()).anyMatch(rp -> rp.contains(":list") || rp.contains(":view"));
            if (isListOrViewAuth) {
                return true;
            }
        }
        throw new DemoException();
    }
}
